﻿namespace Blaze.Editor.Dev.DevPanels
{
    using System.IO;
    using System.Linq;
    using Blaze.UI;
    using CLI;
    using Editor.DevPanels;
    using EditorOnly;
    using Framework;
    using UnityEditor;
    using UnityEngine;

    /// <summary>
    /// 设置面板。
    /// </summary>
    public class SettingDevPanel : DevPanel
    {
        /// <summary>
        /// 获取或设置渠道标识符。
        /// </summary>
        public string Channel
        {
            get
            {
                if (mChannel == null)
                    mChannel = ProjectEditorPrefs.GetString("SettingDevPanel.Channel", AppConfig.channel);
                return mChannel;
            }
            set
            {
                if (mChannel == value)
                    return;
                if (value == null)
                    value = string.Empty;
                mChannel = value;
                ProjectEditorPrefs.SetString("SettingDevPanel.Channel", value);
                AppConfig.channel = value;
                AppConfig.Save();
            }
        }

        /// <summary>
        /// 获取或设置入口服务器的路径。
        /// </summary>
        public string EntryServer
        {
            get
            {
                if (mEntryServer == null)
                    mEntryServer = ProjectEditorPrefs.GetString("SettingDevPanel.EntryServer", AppConfig.entry_server);
                return mEntryServer;
            }
            set
            {
                if (mEntryServer == value)
                    return;
                if (string.IsNullOrEmpty(value))
                    value = "http://20.0.0.249:8038";
                mEntryServer = value;
                ProjectEditorPrefs.SetString("SettingDevPanel.EntryServer", value);
                AppConfig.entry_server = value;
                AppConfig.Save();
            }
        }

        /// <summary>
        /// 获取或设置登录服务器的路径。
        /// </summary>
        public string LoginServer
        {
            get
            {
                if (mLoginServer == null)
                    mLoginServer = ProjectEditorPrefs.GetString("SettingDevPanel.LoginServer", AppConfig.login_server);
                return mLoginServer;
            }
            set
            {
                if (mLoginServer == value)
                    return;
                mLoginServer = value;
                ProjectEditorPrefs.SetString("SettingDevPanel.LoginServer", value);
                AppConfig.login_server = value;
                AppConfig.Save();
            }
        }

        /// <summary>
        /// 获取或设置日志等级。
        /// </summary>
        public int LogLevel
        {
            get
            {
                if (mLogLevel == null)
                    mLogLevel = ProjectEditorPrefs.GetInt("SettingDevPanel.LogLevel", AppConfig.log_level);
                return mLogLevel.Value;
            }
            set
            {
                if (mLogLevel == value)
                    return;
                mLogLevel = value;
                ProjectEditorPrefs.SetInt("SettingDevPanel.LogLevel", value);
                AppConfig.log_level = value;
                AppConfig.Save();
            }
        }

        /// <summary>
        /// 获取或设置一个值，表示是否使用多线程。
        /// </summary>
        public bool Multithreaded
        {
            get
            {
                if (mMultithreaded == null)
                    mMultithreaded = ProjectEditorPrefs.GetBool("SettingDevPanel.Multithreaded", AppConfig.multithreaded);
                return mMultithreaded.Value;
            }
            set
            {
                if (mMultithreaded == value)
                    return;
                mMultithreaded = value;
                ProjectEditorPrefs.SetBool("SettingDevPanel.Multithreaded", value);
                AppConfig.multithreaded = value;
                AppConfig.Save();
            }
        }

        /// <summary>
        /// 获取面板上显示的功能名称。
        /// </summary>
        public override string Name
        {
            get { return "设置"; }
        }

        /// <summary>
        /// 获取开发功能面板的显示优先级。
        /// </summary>
        public override int Priority
        {
            get { return 9999; }
        }

        /// <summary>
        /// 获取或设置资源服务器的路径。
        /// </summary>
        public string ResourceServer
        {
            get
            {
                if (mResourceServer == null)
                    mResourceServer = ProjectEditorPrefs.GetString("SettingDevPanel.ResourceServer", AppConfig.res_server);
                return mResourceServer;
            }
            set
            {
                if (mResourceServer == value)
                    return;
                mResourceServer = value;
                ProjectEditorPrefs.SetString("SettingDevPanel.ResourceServerPath", value);
                AppConfig.res_server = value;
                AppConfig.Save();
            }
        }

        public string ResVersion
        {
            get
            {
                if (mResVersion == null)
                    mResVersion = ProjectEditorPrefs.GetString("SettingDevPanel.ResVersion", AppConfig.res_version);
                return mResVersion;
            }
            set
            {
                if (mResVersion == value)
                    return;
                if (value == null)
                    value = string.Empty;
                mResVersion = value;
                ProjectEditorPrefs.SetString("SettingDevPanel.ResVersion", value);
                AppConfig.res_version = value;
                AppConfig.Save();
            }
        }

        /// <summary>
        /// 获取或设置模拟加载延迟（单位：毫秒）。
        /// </summary>
        public int SimulateLoadingDelay
        {
            get
            {
                if (mSimulateLoadingDelay == null)
                    mSimulateLoadingDelay = ProjectEditorPrefs.GetInt("SettingDevPanel.SimulateLoadingDelay", AppConfig.simulate_loading_delay);
                return mSimulateLoadingDelay.Value;
            }
            set
            {
                if (mSimulateLoadingDelay == value)
                    return;
                mSimulateLoadingDelay = value;
                ProjectEditorPrefs.SetInt("SettingDevPanel.SimulateLoadingDelay", value);
                AppConfig.simulate_loading_delay = value;
                AppConfig.Save();
            }
        }

        /// <summary>
        /// 获取或设置一个值，表示是否模拟真机环境。
        /// </summary>
        public bool SimulateRuntime
        {
            get
            {
                if (mSimulateRuntime == null)
                    mSimulateRuntime = ProjectEditorPrefs.GetBool("SettingDevPanel.SimulateRuntime", AppConfig.simulate_runtime);
                return mSimulateRuntime.Value;
            }
            set
            {
                if (mSimulateRuntime == value)
                    return;
                mSimulateRuntime = value;
                ProjectEditorPrefs.SetBool("SettingDevPanel.SimulateRuntime", value);
                AppConfig.simulate_runtime = value;
                AppConfig.Save();
            }
        }

        /// <summary>
        /// 获取或设置一个值，表示是否跳过闪屏动画。
        /// </summary>
        public bool SkipSplashScreen
        {
            get
            {
                if (mSkipSplashScreen == null)
                    mSkipSplashScreen = ProjectEditorPrefs.GetBool("SettingDevPanel.SkipSplashScreen", AppConfig.skip_splashscreen);
                return mSkipSplashScreen.Value;
            }
            set
            {
                if (mSkipSplashScreen == value)
                    return;
                mSkipSplashScreen = value;
                ProjectEditorPrefs.SetBool("SettingDevPanel.SkipSplashScreen", value);
                AppConfig.skip_splashscreen = value;
                AppConfig.Save();
            }
        }

        protected AppConfig AppConfig
        {
            get { return AppConfigManager.Get<AppConfig>(); }
        }

        /// <summary>
        /// 当需要绘制面板时调用此方法。
        /// </summary>
        public override void OnGUI()
        {
            SkipSplashScreen = GUILayout.Toggle(SkipSplashScreen, "跳过闪屏动画");

            GUILayout.Space(8);

            SimulateRuntime = GUILayout.Toggle(SimulateRuntime, "模拟真机环境");

            GUILayout.Space(8);

            if (SimulateRuntime)
            {
                Multithreaded = true;
            }
            else
            {
                Multithreaded = GUILayout.Toggle(Multithreaded, "启用多线程");

                GUILayout.Space(8);
            }

            RaycastTargetGizmos.Enabled = GUILayout.Toggle(RaycastTargetGizmos.Enabled, "显示RaycastTarget辅助线");
            GUILayout.Space(8);

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("日志等级");
            LogLevel = EditorGUILayout.Popup(LogLevel, mLogLevels, GUILayout.MaxWidth(mRightPartWidth));
            EditorGUILayout.EndHorizontal();

            GUILayout.Space(8);
            SimulateLoadingDelay = drawIntField(SimulateLoadingDelay, "模拟资源加载延迟");

            GUILayout.Space(8);
            EditorGUILayout.BeginHorizontal();
            Adb.ExecutablePath = EditorGUILayout.TextField("adb.exe路径", Adb.ExecutablePath);
            if (GUILayout.Button("Push", GUILayout.Width(48)))
            {
                Adb.ExecutablePath = Adb.ExecutablePath;
                Adb.Push(ProjectPath.Lua, string.Format("/sdcard/Android/data/{0}/files/Lua", PlayerSettings.applicationIdentifier));
            }
            EditorGUILayout.EndHorizontal();

            GUILayout.Space(8);
            ResVersion = mResVersionSettingDrawer.Draw();

            GUILayout.Space(8);
            Channel = mChannelSettingDrawer.Draw();

            GUILayout.Space(8);
            EntryServer = mEntrySettingDrawer.Draw();

            GUILayout.Space(8);
            LoginServer = mLoginSettingDrawer.Draw();
        }

        /// <summary>
        /// 当面板需要初始化的时候调用。
        /// </summary>
        protected override void OnInitialize()
        {
            base.OnInitialize();
            var versions = getIndexNamesFromStreamAssets().Select(p => new ServerSettingShortcut(p, p)).ToArray();
            mResVersionSettingDrawer = new ServerSettingShortcutDrawer("修改资源版本", "SettingDevPanel.ResVersion", versions);

            var entries = BlazeEditorConfig.Instance.EntryServers.Select(config => new ServerSettingShortcut(config.Name, config.Value)).ToArray();
            mEntrySettingDrawer = new ServerSettingShortcutDrawer("修改入口服务器", "SettingDevPanel.EntryServer", entries);

            var logins = BlazeEditorConfig.Instance.LoginServers.Select(config => new ServerSettingShortcut(config.Name, config.Value)).ToArray();
            mLoginSettingDrawer = new ServerSettingShortcutDrawer("修改登录服务器", "SettingDevPanel.LoginServer", logins);

            var channels = BlazeEditorConfig.Instance.Channels.Select(config => new ServerSettingShortcut(config.Name, config.Value)).ToArray();
            mChannelSettingDrawer = new ServerSettingShortcutDrawer("修改渠道号", "SettingDevPanel.Channel", channels);
        }

        private static int drawIntField(int value, string fieldName)
        {
            EditorGUILayout.BeginHorizontal();
            if (!string.IsNullOrEmpty(fieldName))
                GUILayout.Label(fieldName);

            var text = EditorGUILayout.TextField(value.ToString(), GUILayout.MaxWidth(mRightPartWidth));

            EditorGUILayout.EndHorizontal();

            int result;
            if (int.TryParse(text, out result))
                return result;
            return value;
        }

        private static string[] getIndexNamesFromStreamAssets()
        {
            var path = ProjectPath.GetStreamingAssets("fs/indexes");
            if (!Directory.Exists(path))
                return new string[0];
            return Directory.GetFiles(path, "*", SearchOption.AllDirectories)
                .Where(p => !Path.HasExtension(p))
                .Select(p => PathUtility.FormatSeperator(p.Substring(path.Length + 1)))
                .ToArray();
        }

        private const int mRightPartWidth = 128;

        private static readonly string[] mLogLevels = {"All", "Verbose", "Debug", "Warn", "Info", "Error", "Trace", "Off"};
        private int? mLogLevel;
        private bool? mMultithreaded;
        private int? mSimulateLoadingDelay;
        private bool? mSimulateRuntime;
        private bool? mSkipSplashScreen;
        private string mResourceServer;
        private string mLoginServer;
        private string mChannel;
        private string mResVersion;
        private string mEntryServer;
        private ServerSettingShortcutDrawer mResVersionSettingDrawer;
        private ServerSettingShortcutDrawer mEntrySettingDrawer;
        private ServerSettingShortcutDrawer mLoginSettingDrawer;
        private ServerSettingShortcutDrawer mChannelSettingDrawer;
    }
}